package com.zh.note.demo.java8;

import com.zh.note.thread.ThreadPoolFactory;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: zhanghuan
 * @date: 2025/8/26 08:49
 * @description: CompletableFuture详解
 * <p>
 */
public class CompletableFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 需要一个线程池
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolFactory.newThreadPoolExecutor("test", 8, 16, 200, new ThreadPoolExecutor.AbortPolicy());


        /**
         * public static CompletableFuture<Void> runAsync(Runnable runnable)
         *  * public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) 无返回值
         *  * public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
         *  * public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) 有返回值
         */

        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果；" + i);
        }, threadPoolExecutor);

        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果；" + i);
            return i;
        }, threadPoolExecutor).whenCompleteAsync((res, exception) -> {
            //随意能得到异常信息，但是没法修改返回数据
            System.out.println("异步执行成功！结果是：" + res + "异常是：" + exception);
        }).exceptionally(throwable -> {
            return 10;
        });

        /**
         * * public CompletableFuture<Void> thenRun(Runnable action)：不能获取上一步的执行结果
         * * public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor) :不能获取上一步的执行结果
         * * public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor) ：能接受上一步结果，但是无返回值
         * * public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)：能接受上一步结果，有返回值
         */
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果；" + i);
            return i;
        }, threadPoolExecutor).thenRunAsync(() -> {
            System.out.println("任务2启动");
        }, threadPoolExecutor);

        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果；" + i);
            return i;
        }, threadPoolExecutor).thenAcceptAsync((res) -> {
            System.out.println("任务2启动了" + res);
        }, threadPoolExecutor);

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果；" + i);
            return i;
        }, threadPoolExecutor).thenApplyAsync((res) -> {
            System.out.println("任务2启动了" + res);
            return "hello" + res;
        }, threadPoolExecutor);
        String s = future.get();
        /**
         * //可以处理异常，无返回值
         * public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
         * public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
         * public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
         * //可以处理异常，有返回值
         * public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)
         */
        /**
         *  handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行，还可以处理异常的任务。
         *  thenApply 只可以执行正常的任务，任务出现异常则不执行 thenApply 方法。
         * public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
         * public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
         * public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Execut
         */


        /**
         * * thenCombine 会把 两个 CompletionStage 的任务都执行完成后，把两个任务的结果一块交给 thenCombine 来处理
         * * thenAcceptBoth 当两个CompletionStage都执行完成后，把结果一块交给thenAcceptBoth来进行消耗
         */
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1线程结束；" + i);
            return i;
        }, threadPoolExecutor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程");
            System.out.println("任务2结束");
            return "hello";
        }, threadPoolExecutor);

        //当future01和future02两个异步任务都完成时，使用线程池异步执行任务3
        future01.runAfterBothAsync(future02, () -> {
            System.out.println("任务3:");

        }, threadPoolExecutor);

        //当future01和future02两个异步任务都完成时，使用线程池异步执行任务4，并且可以获取前两个任务的结果进行处理
        future01.thenAcceptBothAsync(future02, (f1, f2) -> {
            System.out.println("任务4--->" + f1 + "--->" + f2);
        }, threadPoolExecutor);

        //当future01和future02两个异步任务都完成时，使用线程池异步执行任务5，并且可以获取前两个任务的结果进行处理 同时可以返回前两个任务的结果
        CompletableFuture<String> future1 = future01.thenCombineAsync(future02, (f1, f2) -> {
            System.out.println("任务5");
            return f1 + ":" + f2 + "--->";
        }, threadPoolExecutor);
        String s1 = future1.get();


        /**
         * 多任务组合
         * public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
         * public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品图片信息");
            return "hello.jpg";
        }, threadPoolExecutor);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256G";
        }, threadPoolExecutor);
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的的介绍");
            return "华为";
        }, threadPoolExecutor);
        // futureImg.get();
        // futureAttr.get();
        // futureDesc.get();
        //等待所有任务完成
        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        allOf.get();//等待所有结果完成
        // allOf.join();
        System.out.println(futureImg.get());
        System.out.println(futureAttr.get());
        System.out.println(futureDesc.get());
        //只要有一个任务完成
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureDesc, futureAttr);
        Object o = anyOf.get();

    }
}
